/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin			*/
/*	Project:	GlbCloud			*/
/*	Author:		gong_libin			*/
/*	Date:		2012_01_09			*/
/*	File:		MrEpoll.cpp			*/
/********************************************************/

#include "MrEpoll.h"

CMrEpoll::CMrEpoll()
{
	m_pFunction = NULL;
	m_iEpoll = MR_FAILURE;
}

CMrEpoll::~CMrEpoll()
{
	m_CListen.MrNetClose();
	MrEpollClose();
}

void CMrEpoll::MrEpollClose()
{
	if (m_iEpoll > 0) {
		close(m_iEpoll);
	}

	return;
}

void CMrEpoll::MrEpollSetFunction(int (*pFunction)(int))
{
	m_pFunction = pFunction;

	return;
}

int CMrEpoll::MrEpollGetEpoll()
{
	return m_iEpoll;
}

int CMrEpoll::MrEpollGetListen()
{
	return m_CListen.MrNetGetSocket();
}

int CMrEpoll::MrEpollUdpInit()
{
	return MR_SUCCESS;
}

void CMrEpoll::MrEpollUdpWait()
{
	return;
}

int CMrEpoll::MrEpollTcpInit(char* pszPort)
{
	struct epoll_event stEpoll;

	m_iEpoll = epoll_create(MR_EPOLL);
	if (m_iEpoll < 0) {
		MR_ERROR("%s\n", strerror(errno));
		return MR_FAILURE;
	}

	if (MR_FAILURE == m_CListen.MrTcpInit(pszPort) ) {
		return MR_FAILURE;
	}

	if (MR_FAILURE == m_CListen.MrNetSetNonBlock()) {
		return MR_FAILURE;
	}

	stEpoll.events = EPOLLIN | EPOLLET;
	stEpoll.data.fd = m_CListen.MrNetGetSocket();
	if (MrEpollCtlAdd(&stEpoll) < 0) {
		MR_ERROR("%s\n", strerror(errno));
		return MR_FAILURE;
	}

	return MR_SUCCESS;
}

void CMrEpoll::MrEpollTcpWait()
{
	int iCount = 0;
	int iTotal = 0;
	int iSocket = 0;
	struct epoll_event stEpoll;
	struct sockaddr_in stClient;
	struct epoll_event stEvent[MR_EVENT];
	socklen_t iClient = sizeof(struct sockaddr_in);

	while (true) {
		memset(&stEvent, '\0', sizeof(stEvent));
		iTotal = epoll_wait(m_iEpoll, stEvent, MR_EVENT, -1);
		for (iCount = 0; iCount < iTotal; iCount ++) {
			memset(&stEpoll, '\0', sizeof(struct epoll_event));
			if (stEvent[iCount].data.fd == m_CListen.MrNetGetSocket()) {
				while ((iSocket = accept(m_CListen.MrNetGetSocket(), (struct sockaddr*)&stClient, &iClient)) > 0) {
					fcntl(iSocket, F_SETFL, fcntl(iSocket, F_GETFL, 0) | O_NONBLOCK);
					stEpoll.events = EPOLLIN | EPOLLET;
					stEpoll.data.fd = iSocket;
					MrEpollCtlAdd(&stEpoll);
				}
			}
			else {
				if (0 == (*m_pFunction)(stEvent[iCount].data.fd)) {
					stEpoll.data.fd = stEvent[iCount].data.fd;
					close(stEvent[iCount].data.fd);
					MrEpollCtlDel(&stEpoll);
				}
			}
		}
	}

	return;
}

int CMrEpoll::MrEpollCtlAdd(struct epoll_event* pstEpoll)
{
	return epoll_ctl(m_iEpoll, EPOLL_CTL_ADD, pstEpoll->data.fd, pstEpoll);
}

int CMrEpoll::MrEpollCtlDel(struct epoll_event* pstEpoll)
{
	return epoll_ctl(m_iEpoll, EPOLL_CTL_DEL, pstEpoll->data.fd, pstEpoll);
}
